package com.prince.util;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.apache.commons.collections.bag.SynchronizedSortedBag;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class MapUtil {

	/**
	 * Map key 排序
	 * 
	 * @param map
	 * @return
	 */
	public static Map<String, String> order(Map<String, String> map) {
		HashMap<String, String> tempMap = new LinkedHashMap<String, String>();
		List<Map.Entry<String, String>> infoIds = new ArrayList<Map.Entry<String, String>>(map.entrySet());

		Collections.sort(infoIds, new Comparator<Map.Entry<String, String>>() {
			public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2) {
				return (o1.getKey()).toString().compareTo(o2.getKey());
			}
		});

		for (int i = 0; i < infoIds.size(); i++) {
			Map.Entry<String, String> item = infoIds.get(i);
			tempMap.put(item.getKey(), item.getValue());
		}
		return tempMap;
	}

	/**
	 * map 转对象
	 * 
	 * @param map
	 * @param beanClass
	 * @return
	 * @throws Exception
	 *             T value = (T) parser.parseObject(clazz);
	 */
	public static <T, K, V> T mapToObject(Map<K, V> mp, Class<T> beanCls) {
		T t = null;
		try {
			BeanInfo beanInfo = Introspector.getBeanInfo(beanCls);
			PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
			t = beanCls.newInstance();
			for (PropertyDescriptor property : propertyDescriptors) {
				String key = property.getName();
				if (key.equals("trade_balance")) {
					System.out.println(key);
				}
				if (mp.containsKey(key)) {
					Object value = mp.get(key);
					System.out.println(key + "----" + value);
					Method setter = property.getWriteMethod();
					try {
						setter.invoke(t, value);
					}catch (Exception e) {
						e.printStackTrace();
					}
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return t;
	}

	/**
	 * 转换对象为map
	 * 
	 * @param object
	 * @param ignore
	 * @return
	 */
	public static Map<String, String> objectToMap(Object object, String... ignore) {
		Map<String, String> tempMap = new LinkedHashMap<String, String>();
		for (Field f : getAllFields(object.getClass())) {
			if (!f.isAccessible()) {
				f.setAccessible(true);
			}
			boolean ig = false;
			if (ignore != null && ignore.length > 0) {
				for (String i : ignore) {
					if (i.equals(f.getName())) {
						ig = true;
						break;
					}
				}
			}
			if (ig) {
				continue;
			} else {
				Object o = null;
				try {
					o = f.get(object);
				} catch (IllegalArgumentException e) {
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					e.printStackTrace();
				}
				if (!f.getName().equals("serialVersionUID") && !f.getName().equals("FAIL")
						&& !f.getName().equals("OKMSG") && !f.getName().equals("SUCCESS")
						&& !f.getName().equals("hmac"))
					tempMap.put(f.getName(), o == null ? "" : o.toString());
			}
		}
		return tempMap;
	}

	/**
	 * 转换对象为map
	 * 
	 * @param object
	 * @param ignore
	 * @return
	 */
	public static Map<String, Object> objToMap(Object object, String... ignore) {
		Map<String, Object> tempMap = new LinkedHashMap<String, Object>();
		for (Field f : getAllFields(object.getClass())) {
			if (!f.isAccessible()) {
				f.setAccessible(true);
			}
			boolean ig = false;
			if (ignore != null && ignore.length > 0) {
				for (String i : ignore) {
					if (i.equals(f.getName())) {
						ig = true;
						break;
					}
				}
			}
			if (ig) {
				continue;
			} else {
				Object o = null;
				try {
					o = f.get(object);
				} catch (IllegalArgumentException e) {
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					e.printStackTrace();
				}
				if (!f.getName().equals("serialVersionUID") && !f.getName().equals("FAIL")
						&& !f.getName().equals("OKMSG") && !f.getName().equals("SUCCESS")
						&& !f.getName().equals("hmac"))
					if (null != o) {
						tempMap.put(f.getName(), o == null ? "" : o.toString());
					}
			}
		}
		return tempMap;
	}

	/**
	 * 获取所有Fields,包含父类field
	 * 
	 * @param clazz
	 * @return
	 */
	private static List<Field> getAllFields(Class<?> clazz) {
		if (!clazz.equals(Object.class)) {
			List<Field> fields = new ArrayList<Field>(Arrays.asList(clazz.getDeclaredFields()));
			List<Field> fields2 = getAllFields(clazz.getSuperclass());
			if (fields2 != null) {
				fields.addAll(fields2);
			}
			return fields;
		} else {
			return null;
		}
	}

	/**
	 * url 参数串连
	 * 
	 * @param map
	 * @param keyLower
	 * @param valueUrlencode
	 * @return
	 */
	public static String mapJoin(Map<String, String> map, boolean keyLower, boolean valueUrlencode) {
		StringBuilder stringBuilder = new StringBuilder();
		for (String key : map.keySet()) {
			if (map.get(key) != null && !"".equals(map.get(key))) {
				try {
					String temp = (key.endsWith("_") && key.length() > 1) ? key.substring(0, key.length() - 1) : key;
					stringBuilder.append(keyLower ? temp.toLowerCase() : temp).append("=")
							.append(valueUrlencode ? URLEncoder.encode(map.get(key), "utf-8").replace("+", "%20")
									: map.get(key))
							.append("&");
				} catch (UnsupportedEncodingException e) {
					e.printStackTrace();
				}
			}
		}
		if (stringBuilder.length() > 0) {
			stringBuilder.deleteCharAt(stringBuilder.length() - 1);
		}
		return stringBuilder.toString();
	}

	/**
	 * 简单 xml 转换为 Map
	 * 
	 * @param reader
	 * @return
	 */
	public static Map<String, String> xmlToMap(String xml) {
		try {
			DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
			Document document = documentBuilder.parse(new ByteArrayInputStream(xml.getBytes()));
			Element element = document.getDocumentElement();
			NodeList nodeList = element.getChildNodes();
			Map<String, String> map = new LinkedHashMap<String, String>();
			for (int i = 0; i < nodeList.getLength(); i++) {
				Element e = (Element) nodeList.item(i);

				map.put(e.getNodeName(), e.getTextContent());
			}
			return map;
		} catch (DOMException e) {
			e.printStackTrace();
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		} catch (SAXException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}

	public static boolean isNotEmpty(Map<String, Object> paramMap, String str) {
		if (null != paramMap && null != paramMap.get(str) && !paramMap.get(str).equals("")) {
			return true;
		}
		return false;
	}

	public static boolean isEmpty(Map<String, String> paramMap, String str) {
		if (null != paramMap && null != paramMap.get(str) && !paramMap.get(str).equals("")) {
			return false;
		}
		return true;
	}

	public static boolean isNotEmpty(Map<String, Object> paramMap) {
		if (null != paramMap && paramMap.size() > 0) {
			return true;
		}
		return false;
	}

	public static boolean isNotEmptyList(List<?> paramMap) {
		if (null != paramMap && paramMap.size() > 0) {
			return true;
		}
		return false;
	}

	public static boolean isEmpty(Map<String, Object> paramMap) {
		if (null == paramMap || paramMap.size() == 0) {
			return true;
		}
		return false;
	}

	/**
	 * MD5 加密
	 * 
	 * @param obj
	 * @param key
	 * @return
	 */
	public static String reqSign(Map<String, String> map, String key) {
		String param = MapUtil.mapJoin(MapUtil.order(map), false, false) + "&key=" + key;
		String md5 = Encrypt.md5(param);
		return md5.toUpperCase();
	}

	/**
	 * Map<String, Object> 转 Map<String, String> 
	 * @param param
	 * @return
	 */
	public static Map<String, String> mapToMap(Map<String, Object> param) {
		Map<String, String> map = new TreeMap<>();
		for (Entry<String, Object> entry : param.entrySet()) {
			map.put(entry.getKey(), entry.getValue()+"");
		}
		return map;
	}
	/**
	 * String 转 Map<String, String> 
	 * @param param
	 * @return
	 */
	public static Map<String, String> strToMap(String param) {
		Map<String, String> map = new TreeMap<>();
		if(param.startsWith("{") && param.endsWith("}")) {
			param = param.substring(1,param.length()-1);
		}
		String[] split = param.split(",");
		for (String string : split) {
			String[] split2 = string.split("=");
			map.put(split2[0].trim(), split2[1].trim());
		}
		return map;
	}
	
	public static Map<String,Object> urlToMap(String result){
		String[] split = result.split("&");
		Map<String,Object> map = new HashMap<>();
		for (String str : split) {
			String[] split2 = str.split("=");
			map.put(split2[0], split2[1]);
		}
		System.out.println("url 转Map ：" + map);
		return map;
	}
	
	
	public static String getSign(Map<String,Object> map,String key){
        ArrayList<String> list = new ArrayList<String>();
        for(Map.Entry<String,Object> entry:map.entrySet()){
            if(entry.getValue()!=""){
                list.add(entry.getKey() + "=" + entry.getValue() + "&");
            }
        }
        int size = list.size();
        String [] arrayToSort = list.toArray(new String[size]);
        Arrays.sort(arrayToSort, String.CASE_INSENSITIVE_ORDER);
        StringBuilder sb = new StringBuilder();
        for(int i = 0; i < size; i ++) {
            sb.append(arrayToSort[i]);
        }
        String result = sb.toString()+"key="+key;
        result =MapUtil.encryption(result).toUpperCase();
        System.out.println("加密结果：" +result);
        return result;
    }
	public static String encryption(String plainText) { //上个方法加密
        String re_md5 = new String();
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update(plainText.getBytes());
            byte b[] = md.digest();
            int i;
            StringBuffer buf = new StringBuffer("");
            for (int offset = 0; offset < b.length; offset++) {
                i = b[offset];
                if (i < 0)
                    i += 256;
                if (i < 16)
                    buf.append("0");
                buf.append(Integer.toHexString(i));
            }
            re_md5 = buf.toString();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return re_md5;
    }
}
